package com.example.android.commitcontent.ime.cores.base;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.android.commitcontent.ime.R;

import butterknife.ButterKnife;

/**
 * Created by xuyougen
 * 2019.06.13
 * the base activity, all activities need to extend it.
 */
public abstract class BaseActivity extends AppCompatActivity {

    private FrameLayout content;
    private Point outSize;
    private boolean isExit;
    private float lastX;

    private ImageView ivToolbarBack;
    private ImageView ivToolbarMore;
    private TextView tvToolbarTitle;

    private AlertDialog mLoadingDialog;
    private static final String STR_LOADING_DIALOG_TITLE = "请稍后";
    private static final String STR_LOADING_DIALOG_MESSAGE = "正在执行中";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        initStatusBar();
        super.onCreate(savedInstanceState);
        setContentView(setLayoutRes());
        initLoadingDialog();
        ButterKnife.bind(this);
        outSize = new Point();
        getWindow().getWindowManager().getDefaultDisplay().getSize(outSize);
        setStatusPaddingSize(fid(R.id.ll_toolbar_container));
        initTitleBar();
        setSlideBack();
        initView();
        initData();
    }

    private void initLoadingDialog() {
        mLoadingDialog = new ProgressDialog(this);
        mLoadingDialog.setCancelable(false);
    }

    /**
     * the method is used to init somethings about the status bar ,
     * of course the it's need device's system version 5.0 or higher.
     * 5.0 or higher supports transparent status bar, and 6.0 or higher supports light status bar.
     */
    private void initStatusBar() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
        int uiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            if (isLightStatusBarMode())
                uiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
        } else {
            getWindow().setStatusBarColor(Color.parseColor("#33000000"));
        }
        getWindow().getDecorView().setSystemUiVisibility(uiVisibility);
    }

    protected abstract int setLayoutRes();

    /**
     * you can override the method to set the status bar's mode.
     *
     * @return true is light mode
     */
    protected boolean isLightStatusBarMode() {
        return true;
    }

    private void initTitleBar() {
        ivToolbarBack = fid(R.id.iv_toolbar_back);
        ivToolbarMore = fid(R.id.iv_toolbar_more);
        tvToolbarTitle = fid(R.id.tv_toolbar_title);
        initTitleBarButtonEvent();
    }

    private void initTitleBarButtonEvent() {
        if (checkIsNotNull(ivToolbarBack))
            ivToolbarBack.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    finishPage(null);
                }
            });
        if (checkIsNotNull(ivToolbarMore))
            ivToolbarMore.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                }
            });
    }

    protected void overrideToolbarBackButtonEvent(View.OnClickListener listener) {
        if (checkIsNotNull(ivToolbarBack))
            ivToolbarBack.setOnClickListener(listener);
    }

    protected void overrideToolbarMoreButtonEvent(View.OnClickListener listener) {
        if (checkIsNotNull(ivToolbarMore))
            ivToolbarMore.setOnClickListener(listener);
    }

    protected void setTitleBarText(CharSequence text) {
        if (checkIsNotNull(tvToolbarTitle))
            tvToolbarTitle.setText(text);
    }

    protected void showTitleBackButton() {
        setViewVisibility(ivToolbarBack, View.VISIBLE);
    }

    protected void showTitleMoreButton() {
        setViewVisibility(ivToolbarMore, View.VISIBLE);
    }

    protected void hideTitleBackButton() {
        setViewVisibility(ivToolbarBack, View.GONE);
    }

    protected void hideTitleMoreButton() {
        setViewVisibility(ivToolbarMore, View.GONE);
    }

    private void setViewVisibility(View view, int visibility) {
        if (checkIsNotNull(view))
            view.setVisibility(visibility);
    }

    public void showLoadingDialog() {
        showLoadingDialog(null, null);
    }

    public void showLoadingDialog(@Nullable String title, @Nullable String message) {
        boolean isUseDefault = TextUtils.isEmpty(title);
        mLoadingDialog.setTitle(isUseDefault ? STR_LOADING_DIALOG_TITLE : title);
        mLoadingDialog.setMessage(isUseDefault ? STR_LOADING_DIALOG_MESSAGE : message);
        if (!mLoadingDialog.isShowing()) {
            mLoadingDialog.show();
        }
    }

    public void dismissLoadingDialog() {
        if (mLoadingDialog.isShowing()) {
            mLoadingDialog.dismiss();
        }
    }

    /**
     * add slide back effect, when child views consume the event,
     * it couldn't slide back, so it's not ideally.
     */
    @SuppressLint("ClickableViewAccessibility")
    private void setSlideBack() {
        if (isNeedSlideBack()) {
            content = (FrameLayout) findViewById(android.R.id.content);
            content.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            lastX = motionEvent.getX();
                            if (motionEvent.getRawX() < getResources().getDisplayMetrics().density * 20)
                                return true;
                            break;
                        case MotionEvent.ACTION_MOVE:
                            float x = motionEvent.getRawX();
                            float delta = x - lastX;
                            lastX = x;
                            content.setTranslationX(content.getTranslationX() + delta);
                            break;
                        case MotionEvent.ACTION_UP:
                            isExit = content.getTranslationX() > outSize.x / 3;
                            float start = content.getTranslationX();
                            float end = isExit ? outSize.x : 0;
                            int d = (int) Math.abs(end - start);
                            ValueAnimator animator = ValueAnimator.ofFloat(start, end);
                            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                                    content.setTranslationX((Float) valueAnimator.getAnimatedValue());
                                }
                            });
                            animator.addListener(new Animator.AnimatorListener() {
                                @Override
                                public void onAnimationStart(Animator animator) {

                                }

                                @Override
                                public void onAnimationEnd(Animator animator) {
                                    if (isExit)
                                        finish();
                                }

                                @Override
                                public void onAnimationCancel(Animator animator) {

                                }

                                @Override
                                public void onAnimationRepeat(Animator animator) {

                                }
                            });
                            animator.setInterpolator(new DecelerateInterpolator());
                            animator.setDuration((long) (d / 1.5f));
                            animator.start();
                            break;
                    }
                    return false;
                }
            });
        }
    }

    /**
     * @return a flag to add slide back effect.
     */
    protected boolean isNeedSlideBack() {
        return false;
    }

    /**
     * implement the method to setup with your views.
     */
    protected abstract void initView();

    protected abstract void initData();

    /**
     * the method is usually used to set the xml layout's views' onclick event ,
     * it's the same way to call the finish() method in java codes.
     *
     * @param view
     */
    protected void finishPage(@Nullable View view) {
        finish();
    }

    /**
     * find view by the id , and it auto cast the class type that you want ,
     * and if it not found the view , it will return the null.
     *
     * @param id  the view's id
     * @param <T>
     * @return
     */
    public <T extends View> T fid(int id) {
        View view = findViewById(id);
        if (view == null) return null;
        return (T) view;
    }


    private boolean checkIsNotNull(View view) {
        return view != null;
    }

    /**
     * get system status bar's height
     *
     * @return height pixels.
     */
    public static int getStatusBarHeight() {
        Resources resources = Resources.getSystem();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }

    public static void setStatusPaddingSize(View view) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || view == null) return;
        int statusBarHeight = getStatusBarHeight();
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params.height > 0) {
            params.height += statusBarHeight;
            view.setLayoutParams(params);
        }
        view.setPadding(view.getPaddingLeft(),
                view.getPaddingTop() + statusBarHeight,
                view.getPaddingRight(),
                view.getPaddingBottom());
    }

}
